perm filename MODEM.MAC[1,ALS] blob
sn#687561 filedate 1982-12-01 generic text, type T, neo UTF8
debug==1
;<BILLW>MODEM.MAC.52, 7-Oct-82 14:04:40, Edit by BILLW
; fixed several bugs in TAC/TIP code (TACs arent the same
; as TIPs - they also need WILL TRNBIN)
; support of ITS/LMODEM .COM file format, and automatic detection of same.
; (sixbit/DSK8/ in word 0, rest just 4 8bit bytes/word) ("I" option)
; DMESG debugging macro writes to MODEM-DEBUG.LOG file
; fixed transmission of extra block for file with even number of blocks
;<BILLW>MODEM.MAC.25, 27-Sep-82 16:51:41, Edit by BILLW
; make it work woth Tip/TAC ARPANet connections
; DO TRANSMIT BINARY negotiaition
; transmit FFs twice
; turn off PAUSE (on) COMMAND mode
; check for incrementing block numbers
; fix bug that typed backspaces even when using .priou for transfer
; leave null instead of ↑Z at EOF
; (thanks to Ted Shapin (ADMIN.SHAPIN@isib) for the original fixes to
; some of these problems, and to Frank Wancho, (FJW@MIT-MC) who
; explained how to make it work over the ARPANet)
;<BILLW>MODEM.MAC.158, 19-Jul-82 13:46:23, Edit by BILLW
; re-enable links on exit.
;<BILLW>MODEM.MAC.154, 2-Jul-82 18:09:37, Edit by BILLW
; made time-out time dependent on trasmission speed
title MODEM File transfer program for MICROS <-> TOPS-20
; Written By Bill Westfield for SRI International Networks Group
; Bugs/suggestions/uestions to BillW@SRI-KL
comment }
This program is a Tops-20 implementation of the defacto-standard
MODEM2 File Transfer Protocol as devised by Ward Christensen?.
The protocol itself is documented in SRI-KL:<MICRO>MODEM2.PROTO
This program attempts to implement to standard user interface,
IE you type commands like:
MODEM <options><suboptions> FILE
to the Twenex EXEC
Hooks are included to use an autodialer or a TTY line when
the Tops-20 system is the "Master" console...
}
search MONSYM,MACSYM
F== 0
P== 17
A== 15
B== 16
CHKSUM= 13
RECNUM= 14
EOT== "D"-100
ACK== "F"-100
NAK== "U"-100
SOH== "A"-100
SUB== "Z"-100
CAN== "X"-100
IAC== 377 ;arpanet telnet IAC
WILL== 373 ; telnet will <option>
WONT== 374
DO== 375 ; telnet do <option>
DONT== 376 ; telnet don't <option>
TRNBIN== 0 ; transmit binary
F%S== 1,,0 ;view sent characters
F%R== 2,,0 ;view received characters
F%V== 4,,0 ;view data only
F%T== 10,,0 ; go into terminal mode
F%E== 20,,0 ; go into echo mode
F%D== 40,,0 ;disconnect when done
F%Q== 100,,0 ;transfer without messages
F%A== 200,,0 ;ascii
F%B== 400,,0 ;binary
F%DEB== 1000,,0 ;debug connection to PTY open
F%CAP== 2000,,0 ;capabilities were enabled
F%COMM==4000,,0 ;go to command mode
F%ARPA==10000,,0 ; try to work over ARPANet connection
F%ITS== 20000,,0 ;use ITS style binary file
ifndef TIMFAC,<TIMFAC=<3.0>> ; N times the transmission time
ifndef DEBUG,<DEBUG==0>
ifndef USEBIN,<USEBIN==0>
ife DEBUG,<define dmesg(n1,t1,n2,t2) <>>
ifn DEBUG,<define dmesg(n1,t1,n2,t2)<
push p,1
push p,2
push p,3
push p,4
move 1,DBGJFN
seto 2,
movsi 3,(OT%NDA)
odtim
movei 2,11
bout
ifnb <n1>,<ifg n1-4,<move 2,n1>
ifle n1-4,<move 2,<4-n1>(p)>
movei 3,10
nout
trn >
hrroi 2,[asciz/t1/]
setzb 3,4
sout
ifnb <n2>,<ifg <n2-4>,<move 2,n2>
ifle <n2-4>,<move 2,<4-n2>(p)>
movei 3,10
nout
trn >
setzb 3,4
ifnb <t2>,<hrroi 2,[asciz/t2/]
sout >
hrroi 2,[byte(7) 15,12,0]
sout
pop p,4
pop p,3
pop p,2
pop p,1
>>
BUFSIZ==200 ; 128 character buffers
opdef call [pushj P,0]
opdef ret [popj P,0]
BEGCTR== 0
SAVCTR== 0
DEFINE %IF
<BEGCTR==BEGCTR+1
JRST <%GTNAM(BEG,\BEGCTR)>
SAVCTR==SAVCTR+1
%STNAM(SAV,\SAVCTR,BEGCTR)>
DEFINE %ELSE
<%VAL==%GTNAM(SAV,\SAVCTR)
BEGCTR==BEGCTR+1
JRST <%GTNAM(BEG,\BEGCTR)>
%STNAM(BEG,\%VAL,.)
%STNAM(SAV,\SAVCTR,BEGCTR)>
DEFINE %END
<%VAL==%GTNAM(SAV,\SAVCTR)
SAVCTR==SAVCTR-1
%STNAM(BEG,\%VAL,.)>
DEFINE %GTNAM(VAR,IND) <VAR'IND>
DEFINE %STNAM(VAR,IND,VAL) <VAR'IND=VAL>
define UBIN<ifn USEBIN>
define USIN<ife USEBIN>
START: reset
setz F, ;zero flags
ifn DEBUG,<
movsi 1,(GJ%SHT)
hrroi 2,[asciz/MODEM-DEBUG.LOG;p777777/]
gtjfn
trn
move 2,[7b5 + of%app]
openf
trn
movem 1,DBGJFN#
>
movei 1,.priou
rfcoc
dmovem 2,OLDCOC
dmove 2,[byte(2) 1,1,1,1,1,1,1,2,2,3,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1] ;echo CR, LF, BS, and TAB properly
sfcoc
rfmod
movem 2,OLDMOD
and 2,[↑-TT%PGM] ;Turn off pause on command
STPAR% ;So block 13H doesn't stop receiving
dvchr
andi 3,-1 ; get terminal number
movei 1,.PTYPAR ; get first PTY number
getab
trn
hlrz 2,1 ; isolate number of PTYs
addi 2,(1) ; first NVT is first PTY + NPTYs
camge 3,2
%IF
hrroi 1,[asciz/
ARPANet NVT special processing will be performed.
/]
psout
tro F,(F%ARPA)
%END
; No system messages please!
movx 1,.CTTRM ;Get current refuse
movx 2,.MORNT ; seting.
mtopr
trn
movem 3,OLDSYS# ;Old sys message status.
movx 2,.MOSNT ;For sys messages.
movx 3,.MOSMN ;Turn them off.
mtopr
; Clear and refuse links
movx 1,<TL%CRO!TL%COR!TL%SAB!TL%STA!.CTTRM>
seto 2, ;Clear all links.
tlink
trn
move P,PDLPTR
movei 1,.FHSLF ;enable interupts
move 2,[LEVTAB,,CHNTAB]
sir ; just like in the book
eir
hrlzi 2,400000 ; just activate one channel
aic
movsi 1,(GJ%SHT)
hrroi 2,[asciz/MODEM-DEVICE:/]
gtjfn ;save device we are using as
setz 1, ; the data channel (from previous
movem 1,MODDEV ; invocation of MODEM)
jumpe 1,FRESH
move 2,[10b4 ! OF%RD ! OF%WR]
openf
jrst DEVERR
setz 2,
sfmod
FRESH: jumpn 1,.+3
movei 1,.priou
movem 1,MODDEV
setz 1,
rscan
setz 1,
jumpe 1,NOCMDS ;no commands ?
LOOK1: pbin
cain 1,12
jrst NOCMDS
caie 1,40 ;space indicates start of commands
jrst LOOK1
movei 1,.priin
hrroi 2,CMDBUF
movei 3,100
movei 4,12
sin ; get commands into buffer
cfibf ; discard any other input
PARSE: move A,[point 7,CMDBUF]
PRIMOP: ildb 1,A ;get primary option
cain 1,40
jrst PRIMOP
caie 1,"r"
cain 1,"R"
jrst RECEIVE
caie 1,"s"
cain 1,"S"
jrst SEND
caie 1,"E"
cain 1,"e"
jrst ECHO
caie 1,"T"
cain 1,"t"
jrst TERMINAL
caie 1,"C"
cain 1,"c"
jrst DIAL
caie 1,"d"
cain 1,"D"
jrst DISCONNECT
caie 1,"x"
cain 1,"X"
jrst EXAMPLE
HELP: caie 1,"H"
cain 1,"h"
skipa 1,[-1,,HLPTXT]
hrroi 1,[asciz/Use MODEM H for help
/]
psout
jrst CMDLP ;another comand, or exit
NOCMDS: setom CMFLAG
CMDLP: call SETTIM
trn ;turn off interupts
tlzn F,(F%CAP)
%IF
movei 1,-5
move 2,OLDTIW
stiw ;restore previous Interupt word
movei 1,.FHSLF
rpcap
move 3,OLDCAP
epcap ;disable capabilities
%END
movei 1,.priou
move 2,OLDMOD
sfmod
trze F,(F%COMMA) ;go to command mode ?
setom CMFLAG
trze F,(F%T) ;go to terminal mode ?
jrst TERMINAL
trze F,(F%E) ; or echo mode ?
jrst ECHO
trze F,(F%D)
jrst DISCONNECT
skipn CMFLAG
jrst HALT
trz F,↑-(F%ARPA) ;clear temporary bits
hrroi 1,[asciz/MODEM>/]
psout
hrroi 1,CMDBUF
move 2,[RD%BEL + 100]
hrroi 3,[asciz/MODEM>/]
rdtty
jrst CMDLP
jrst PARSE ;execute the comand line
HALT: movx 1,.CTTRM
move 3,OLDSYS# ;Old sys message status.
movx 2,.MOSNT ; Restore state
mtopr
move 4,OLDMOD ;get old link bits
movei 1,-1
trne 4,TT%ALK ;accept links ?
tlo 1,(TL%SAB!TL%ABS)
trne 4,TT%AAD ;accept advise ?
tlo 1,(TL%STA!TL%AAD)
movei 2,-1
tlink ;maybe re-enable links/advice
trn
movei 1,.priou
dmove 2,OLDCOC
sfcoc ;restore control character echoing
trnn F,(F%ARPA)
%IF
setz 2,
sfmod
dmove 2,[exp <point 8,[byte(8) IAC,WONT,TRNBIN]>,-3]
sout
movei 1,↑d4000
disms
movei 1,.priou
dmove 2,[exp <point 8,[byte(8) IAC,DONT,TRNBIN]>,-3]
sout
%END
move 2,OLDMOD
sfmod
stpar ;restore pause commands
ifn DEBUG,<move 1,DBGJFN
closf
trn >
haltf
haltf
jrst start
subttl SEND a file
SEND: call SUBOPT ;get sub options
dmesg ,<SENDing file>
setzm EOFFLG
movsi 1,(GJ%SHT ! GJ%OLD)
move 2,A
gtjfn
jrst SNDERR
call IPNFIL ;open file depending on mode
skipn 1,MODDEV ; dialer or third line in use?
move 1,.priou ;send to normal channel
movem 1,OUTJFN
setz 2,
sfmod
trnn F,(F%ARPA)
%IF
dmesg ,<sending DO TRNBIN to TIP>
dmove 2,[exp <point 8,[byte(8) IAC,WILL,TRNBIN]>,-3]
sout
push P,1
movei 1,↑d4000
disms
move 1,(P)
dmove 2,[exp <point 8,[byte(8) IAC,DO,TRNBIN]>,-3]
sout
movei 1,↑d4000
disms
pop P,1
%END
caie 1,.priou ; output directly to teminal ?
trne F,(F%Q!F%R!F%S) ; or noisy mode
%IF
hrroi 1,[asciz/
Block /]
psout
%END
call GETTIM ;set timout time
setz RECNUM, ;zero record number
call GETCHR
caie 2,NAK ;wait for initial NAK
jrst .-2
dmesg ,<Initial NAK received>
NEXT: move 1,OUTJFN
cfibf
movei 1,12
movem 1,ERRCNT#
skipn EOFFLG ;have we reached the end of the file ?
%IF
DOEOF: dmesg ,<Sending EOF>
movei 2,4 ;if EOF then
call SNDCHR
call GETCHR ; and then wait for <ack> back
call CLSFIL
jrst CMDLP ; and exit
%END
call GETBUF ;get a buffers worth from file
jumpe 3,DOEOF ; if 0 bytes read, send EOF
addi RECNUM,1
movei 1,12
movem 1,TIMCNT ;reset timeout count
AGAIN: dmesg ,<Transmitting block >,RECNUM
setz CHKSUM,
call SNDHEADER
move 2,[point 8,buffer]
movni 3,BUFSIZ
call SNDSTR ;transmit the buffer
call CSUM
move 2,CHKSUM
call SNDCHR ;and follow with a check-sum
ACKWAIT:
call SETTIM ;set time limit for waiting
jrst AGAIN ; what to do if we time out
call GETCHR ;wait for ACK or NAK
cain 2,6
jrst NEXT1 ;all OK, transmit next sector
caie 2,"U"-100 ; oh dear, a NAK...
jrst [dmesg 2,<received, not ACK or NAK>
jrst ACKWAIT] ;must be one or the other
dmesg ,<NAK received>
sosle ERRCNT#
jrst AGAIN ; we will try again
hrroi 1,[asciz/10 consectutive NAKs received. Transfer aborted
/]
psout
jrst CMDLP
NEXT1: dmesg ,ACK received
move 1,OUTJFN
caie 1,.priou ; output not going directly to terminal
trne F,(F%Q!F%R!F%S) ; or noisy mode
%IF
hrroi 1,[byte(7) 10,10,10]
psout
movei 1,.priou
movei 2,(RECNUM)
move 3,[NO%LFL + <3,,12>]
nout
trn
%END
jrst NEXT
SNDHEADER:
movei 2,1 ;Start of heading
call SNDCHR
movei 2,(RECNUM) ; Record number
call SNDCHR
setca 2, ; Not (Record Number)
call SNDCHR
ret
SNDERR: hrroi 1,[asciz/SEND error
/]
psout
jrst ERRMSG
Subttl Receive A file
RECEIVE:
call SUBOPT ;get sub options
movsi 1,(GJ%SHT!GJ%FOU)
move 2,A
gtjfn
jrst RCVERR
call OPNFIL ;open file depending on mode
skipn 1,MODDEV ; dialer or third line in use?
move 1,.priou ;send to normal channel
movem 1,OUTJFN
setz 2,
sfmod
trnn F,(F%ARPA)
%IF
dmesg ,<sending DO TRNBIN to TIP>
dmove 2,[exp <point 8,[byte(8) IAC,DO,TRNBIN]>,-3]
sout
push P,1
movei 1,↑d4000
disms
movei 1,↑d4000
disms
move 1,(P)
dmove 2,[exp <point 8,[byte(8) IAC,WILL,TRNBIN]>,-3]
sout
movei 1,↑d4000
disms
pop P,1
%END
push P,1
cain 1,.priou ;using control terminal ?
call DISINT ; disable ↑C interupts
call GETTIM ;get time-out time
pop P,1
caie 1,.priou ; output directly to teminal ?
trne F,(F%Q!F%R!F%S) ; or noisy mode
%IF
hrroi 1,[asciz/
Block /]
psout
%END
setz RECNUM, ;zero record number
setzm LSTREC ; pretend already received block 0
movei 1,12
movem 1,TIMCNT ;reset time-out count
SNDNAK: movei 2,NAK
call SNDCHR
RCVLP: setz CHKSUM,
call SETTIM
jrst SNDNAK ;what todo on time-out
WAIT: call GETCHR ;should be SOH
cain 2,EOT ; end of file ?
jrst RCVDONE ; finished
cain 2,CAN
jrst ABORT
caie 2,SOH
jrst WAIT
addi CHKSUM,(2)
call GETCHR ;record number
movem 2,RECSAV# ; save it...
addi CHKSUM,(2)
call GETCHR
addi CHKSUM,(2) ;complemented record number
andi CHKSUM,377
jumpn CHKSUM,WAIT ; SOH + CHKSUM + ↑-CHKSUM should be 0
move 2,[point 8,BUFFER]
movni 3,BUFSIZ
call GETSTR ;get the block
call CSUM ;compute Check sum
call GETCHR ;get foriegn computers check sum
andi CHKSUM,377 ;only 8 bits
caie 2,(CHKSUM) ; see if they match...
jrst SNDNAK
;OK, we now have a valid block of data. Check if it is an "extra copy"
move 2,RECSAV ;get back record number
camn 2,LSTREC ; same ?
%IF ; no...
exch 2,LSTREC
addi 2,1
andi 2,377
exch 2,LSTREC
came 2,LSTREC
%IF
call PUTBUF ; yes, write it to disk
%ELSE
hrroi 1,[asciz/Block synchronization lost./]
esout
jrst ABORT
%END
%END
movem 2,LSTREC ; save record number
move 1,OUTJFN
caie 1,.priou ; output directly to teminal ?
trne F,(F%Q!F%R!F%S) ; Noisy mode ?
%IF
hrroi 1,[byte(7) 10,10,10]
psout
movei 1,.priou
move 3,[NO%LFL + <3,,12>]
nout
trn
%END
movei 2,ACK
call SNDCHR ;send positive acknoledgement
movei 1,12
movem 1,TIMCNT
jrst RCVLP ; and get next block
RCVDONE:
movei 2,ACK
call SNDCHR
call CLSFIL
jrst CMDLP
ABORT: seto 1,
rljfn
trn
hrroi 1,[asciz/Aborted/]
esout
jrst CMDLP
RCVERR: hrroi 1,[asciz/RECEIVE error
/]
psout
jrst ERRMSG
Subttl Make a call to TTY port or auto-dialer
DIAL: ildb 1,A ;get next character
cail 1,"a"
subi 1,40 ; upper-casify
cain 1,"T"
jrst TRYTTY ;try a terminal
cain 1,":"
jrst TRYHST ;try a host name
caig 1,"9"
caige 1,"0" ;is it a digit ?
jrst CALERR
;;;*** Auto dialer code goes here
hrroi 1,[asciz/Sorry, no Autodialers yet.
/]
psout
ildb 1,A
caig 1,"9"
caige 1,"0"
trna
jrst .-4
call SUBOPT
jrst CMDLP
CALER1: skipa 1,[-1,,[asciz/Illegal argument to "C" option
/]]
CALERR: hrroi 1,[asciz/Error dialing number or acquiring TTY line
/]
psout
jrst ERRMSG
Subttl make a "call" to a terminal line
TRYTTY: ildb 1,A ;next character
cail 1,"a"
subi 1,40
caie 1,"T" ; also a T ?
jrst TTYNUM
ildb 1,A ; "Y"...
cail 1,"a"
subi 1,40
caie 1,"Y"
jrst TTYNUM
ildb 1,A
TTYNUM: cain 1,"D"
jrst TDEBUG
setz 2,
caig 1,"9"
caige 1,"0"
jrst CALERR
TTYLP: imuli 2,10
addi 2,-60(1)
ildb 1,A
caig 1,"9"
caige 1,"0"
jrst TTYDON
jrst TTYLP
TTYDON: push P,2
add A,[7b5] ;back up byte pointer
skipge A ; .
sub A,[43b5+1] ; .
call SUBOPT ;get sub options
pop P,2
call OPNTTY
jrst CMDLP
OPNTTY: hrroi 1,DEVNAM
addi 2,400000 ;create device number
push P,2
devst
jrst CALERR
movei 2,":"
idpb 2,1 ;create name TTYnnn:
movei 1,.CLNJ1
hrroi 2,[asciz/MODEM-DEVICE/]
setz 3, ;delete old name, if any
crlnm
trn
movei 1,.CLNJB
hrroi 2,[asciz/MODEM-DEVICE/]
hrroi 3,DEVNAM
crlnm
jrst CALERR
pop P,1
asnd ;assign device to my job
jrst CALERR
hrroi 2,[asciz/MODEM-DEVICE:/]
movsi 1,(GJ%SHT)
gtjfn ; get a handle on it
jrst CALERR
movem 1,MODDEV
move 2,[10b4 ! OF%RD ! OF%WR]
openf ;and finally, open as modem device
jrst CALERR
setz 2,
sfmod
ret
TDEBUG: call SUBOPT
hrroi 1,[asciz/Getting a PTY.../]
psout
tlo F,(F%DEB)
move 1,['PTYPAR']
sysgt
hrrzm 1,FIRPTY#
movsi 1,(GJ%SHT)
hrroi 2,[asciz/PTY12:/]
gtjfn
jrst CALERR
movem 1,MODDEV
move 2,[10b5+of%rd+of%wr]
openf
jrst CALERR
dvchr
hrrzi 1,(1) ;get just unit number
add 1,FIRPTY
tro 1,400000 ;change to TTY number
movem 1,PTYDD
movei 2,3
move 1,MODDEV
bout ;send ↑C
jrst CMDLP
Subttl make a connection to a host, given its name.
NOTIMP: hrroi 1,[asciz/Host not supported yet.
/]
psout
jrst CMDLP
TRYHST: push P,A ;save start of host name
ildb 1,A
caile 1,"A" ; punctuation ?
jrst .-2
push P,A
call SUBOPT ;get sub-options
pop P,1
setz 2,
dpb 2,1 ;terminate host name with null
pop P,2 ;get start of host name back
movei 1,HSTTAB ;tabel of host names
tbluk
tlne 2,(TL%NOM)
jrst NSHOST ;no such host
tlne 2,(TL%AMB)
jrst AMHOST ;ambiguous host
hrrz 1,(1) ;get routine
call (1)
jrst CMDLP
define tba(HOSTNAME,DIALROUTINE)
< [asciz/HOSTNAME/],,<DIALROUTINE> >
HSTTAB: HSTLEN,,HSTLEN
tba CRVAX,CRVAX ;CR's VAX 780
tba IBMPC,NOTIMP ;CR's IBM persoal computer
tba MICOM,DOMICM ;the micom
tba VLSIVAX,NOTIMP ;TSC's VLSI VAX 750
HSTLEN== .-HSTTAB-1
Subttl Individual Host routine
DOMICM: ;;;connect to the CR MICOM
movei 2,124 ;TTY conected to MICOM
call OPNTTY
move 1,MODDEV
movei 2,15
bout ;send CR
ret
CRVAX: call DOMICM ;first get micom
call FLUSH
movei 2,15
bout
call FLUSH
movei 2,"V"
bout
call FLUSH
movei 2,15
bout
call FLUSH
movei 2,15
bout
ret
FLUSH: movei 1,↑d1500
disms
move 1,MODDEV
sibe
jrst .+2
ret
FLUSH1: bin
; movei 1,.priou
; bout
; move 1,MODDEV
sibe
jrst FLUSH1
jrst FLUSH
AMHOST: hrroi 1,[asciz/Ambiguous host name
/]
psout
jrst CMDLP
NSHOST: hrroi 1,[asciz/No such host name
/]
psout
jrst CMDLP
Subttl TERMINAL and ECHO modes
TERMINAL:
trz F,(F%S!F%R!F%V) ;dont view characters
movei 1,.priou
setz 2,
sfmod ;set 8 bit/no echo mode
cain 1,.priou ;using control terminal ?
call DISINT ;diable ↑C, etc
TERMLP: movei 1,.priin
sibe
jrst GETTTY
TSTPTY: tlne F,(F%DEB)
%IF
move 1,MODDEV
sibe
jrst GETMOD ;need to get a char from MODEM device
%ELSE
move 1,PTYDD
sobe
jrst GETMOD
%END
movei 1,400
disms
jrst TERMLP
GETTTY: bin
move 1,MODDEV
cain 2,"E"-100
jrst CMDLP
bout
movei 1,.priin
sibe
jrst GETTTY
jrst TSTPTY
GETMOD: move 1,MODDEV
bin
movei 1,.priou
bout
tlne F,(F%DEB)
%IF
move 1,MODDEV
sibe
jrst GETMOD
%ELSE
move 1,PTYDD#
sobe
jrst GETMOD
%END
jrst TERMLP
ECHO: jrst TERMINAL
Subttl Disconnect command
DISCONNECT:
setzm CMFLAG
move 1,MODDEV
hrli 1,(CO%NRJ)
closf ;close device
trn
movei 1,(1)
dvchr
reld ;deassign it
trn
movei 1,.CLNJ1
hrroi 2,[asciz/MODEM-DEVICE/]
setz 3, ;delete logical name...
crlnm
trn
seto 1,
rljfn ; finally release the JFN
trn
jrst CMDLP
Subttl TIMER routines
; Call is:
; pushj P,SETTIM
; <instruction to execute if time limit is exceeded>
;
; SETTIM always takes the skip return
; the instruction to be executed should be a jrst, as it
; is implemented by setting the interupt return address to
; that instruction. if the instructio is TRN, then all
; interupts are cleared....
SETTIM: move 1,[.FHSLF,,.TIMAL]
setzb 2,3
timer
trn
move 4,(P)
movem 4,INTINS
hlrz 4,(4)
cain 4,(trn)
jrst CPOPJ1
move 1,[.FHSLF,,.TIMEL]
skipn 2,TIMTIM ;get timeout time
movei 2,↑d10000 ;10 seconds if not specified
setz 3,
timer
trn
CPOPJ1: aos (P)
CPOPJ: ret
INTER: move P,PDLPTR
sosl TIMCNT#
jrst INTER2
hrroi 1,[asciz/10 Consecutive time-outs. Aborting transfer
/]
psout
jrst CMDLP
INTER2: push P,2
ifn DEBUG,<hrrz 2,PCLEV1> ; the PC at which the timeout occured
push P,INTINS ;alter return address
pop P,PCLEV1
dmesg ,<Timout at PC >,2
trne F,(F%Q)
%IF
push P,1
push P,3
hrroi 1,[asciz/ Timeout /]
psout
ifn debug,<
movei 1,.priou
movei 3,10
nout
trn
pop P,3
pop P,1 >
%END
pop P,2
debrk ;and dismis interupt
GETTIM: ;;; This routine sets up the timeout time as being 3 times
; The length of time that it should take to transmit a
; full packet based on the terminal speed of transfer line.
move 1,OUTJFN
movei 2,.MORSP ;get terminal speeds
mtopr
erjmp CPOPJ
jumpl 3,CPOPJ ; if unspecified use default time
hlrz 2,3 ;input speed
hrrz 2,2 ;output speed
camle 2,3
move 2,3 ;take the minimum speed
idivi 2,12 ;characters per second
fltr 2,2 ;float it
move 3,[<128000.0>] ; TIMFAC * tranmission time
fmpri 3,(TIMFAC)
fdvr 3,2 ;convert to milliseconds per packet
fix 3,3
caige 3,↑d3000 ;wait at least 1.5 seconds though
movei 3,↑d3000
ifn debug,<movei 3,↑d10000>
movem 3,TIMTIM
ret
DEVERR:
EXAMPLE:
ERRMSG: move P,PDLPTR
jrst CMDLP
SNDCHR: move 1,OUTJFN
andi 2,377
bout ;send to output channel
cain 2,377 ; FFs must be sent twice...
trnn F,(F%ARPA) ; ...on ARPANet connections.
%IF
cain 1,.priou
bout
%END
movei 1,.PRIOU
trne F,(F%S) ; show Sent characters ?
bout ; yes, send to command terminal too
ret
GETCHR: move 1,OUTJFN
bin
movei 1,.priou
trne F,(F%R) ;show Received characters ?
bout ; yes
ret
SNDSTR: move 1,OUTJFN
push P,3
push P,2
cain 1,.PRIOU
trnn F,(F%ARPA)
%IF
movn 3,3 ;ahh ARPANet - must quote FFs,
movei 4,377 ; so use + length, and FF as EOS
%END
SNDBAR: sout ;send block to other computer
erjmp SNDFOO ;stricktly for PTY debug mode
cain 3,0 ; sent the whole string ?
%IF
push p,2 ; if not, must be because string
movei 2,377 ; contains an FF that must be
bout ; quoted with itself. So do it.
pop p,2
jrst SNDBAR
%END
pop P,2
pop P,3
movei 1,.priou
trne F,(F%S!F%V) ;show Sent characters or view file ?
sout
ret
SNDFOO: movei 1,300
disms ;wait for other process to read
move 1,OUTJFN ; characters out of buffer
jrst SNDBAR ;send rest of string
GETSTR:
USIN,< push P,3
push P,2
move 1,OUTJFN
sin
pop P,2
pop P,3
movei 1,.PRIOU
trne F,(F%R ! F%V)
sout
ret
>;USIN
UBIN,< push P,3
push P,2
push P,4
move 4,2
BINLP: move 1,OUTJFN
bin
idpb 2,4
movei 1,.priou
trne F,(F%R ! F%V)
bout
aojl 3,BINLP
pop P,4
pop P,2
pop P,3
ret
>;UBIN
DISINT: tlo F,(F%CAP)
movei 1,-5
rtiw
movem 2,OLDTIW# ;save old Terminal interupt word
movei 1,.fhslf
rpcap
movem 3,OLDCAP# ;save old capabilities
tlo 3,(SC%CTC)
epcap
movei 1,-5
setzb 2,3
stiw ;disable ↑C interupts
Subttl CSUM
CSUM: move 1,[point 8,BUFFER]
movei 2,BUFSIZ
ildb 3,1
addi CHKSUM,(3)
sojg 2,.-2
ret
GETBUF: move 1,[byte(8) 32,32,32,32] ; fill buffer with ↑Zs
movem 1,BUFFER
move 1,[BUFFER,,BUFFER+1]
blt 1,BUFFER+<BUFSIZ/4+2>
move 1,FILJFN
move 2,[point 8,buffer]
movni 3,bufsiz
sin
ercal GETEOF
addi 3,200 ;compute number of bytes read
ret
GETEOF: setom EOFFLG
ret
PUTBUF: push P,2
move 1,FILJFN
move 2,[point 8,BUFFER]
movni 3,BUFSIZ
movei 4,SUB
trnn F,(F%B) ;stop on ↑Z for text files
movn 3,3
sout
cain 3,0 ; stopped on ↑Z ?
%IF
rfptr
setz 2,
subi 2,1 ;then try to get rid of it
sfptr ; by decrementing file size..
trn
setz 2,
bout
%END
pop P,2
ret
CLSFIL: move 1,FILJFN
trnn F,(F%ITS)
%IF
movei 2,44
sfbsz
trn
%END
closf
trn
ret
OPNFIL: skipa 2,[of%wr]
IPNFIL: move 2,[of%rd]
trne F,(F%A!F%B!F%ITS) ;Explicit binary or Ascii mode ?
%IF
push P,2
move 2,[1,,.FBBYV]
movei 3,4
gtfdb
lsh 4,-<↑d35-↑d11>
andi 4,77
caie 4,10 ;8 bit bytes ?
%IF
push P,1
hrroi 1,[asciz/(*** Tops-20 Binary Mode assumed ***)
/]
psout
tro F,(F%B)
pop P,1
%END
caie 4,44 ;36 bit bytes ?
%IF
push P,1
hrroi 1,[asciz/(*** ITS binary mode assumed ***)
/]
psout
tro F,(F%ITS!F%B)
pop P,1
%END
pop P,2
%END
hrli 2,(7b5) ;assume ascii mode
trne F,(F%B) ;unless binary was requested
hrli 2,(10b5)
openf
jrst FILERR
movem 1,FILJFN
trnn F,(F%ITS) ;ITS mode ?
%IF ; look for or write DSK8 word
trnn 2,OF%WR
%IF
dmove 2,[exp <point 8,[byte(8) 223,72,330,0]>,<-4>]
sout ; write sixbit/DSK8/
%ELSE
bin ;or check for sixbit/DSK8/
caie 2,223
jrst NOTITS
bin
caie 2,72
jrst NOTITS
bin
caie 2,330
jrst NOTITS
bin
jumpn 2,NOTITS
%END
%END
ret
NOTITS: hrroi 1,[asciz/(*** no DSK8 word in ITS file. ***)
/]
psout
hrroi 1,[asciz/(*** Text mode assumed ***)
/]
psout
move 1,FILJFN
setz 2,
sfptr
jrst FILERR
movei 2,7
sfbsz
jrst FILERR
ret
FILERR: hrroi 1,[asciz/File open error
/]
psout
jrst ERRMSG
Subttl Get sub-options
SUBOPT: ildb 1,A
caie 1,12
cain 1,0
ret
cail 1,"a"
subi 1,40 ;upper case-ify
caie 1,15
cain 1,40
ret
setz 2,
OPTLP: hlrz 3,SUBTAB(2)
jumpe 3,OPTERR
caie 1,(3)
aoja 2,OPTLP
hrrz 1,SUBTAB(2)
tro F,(1) ;set appropriate bit
jrst SUBOPT
define $SUB(a) <"a",,(F%'a)>
SUBTAB: $SUB S ;type SENT characters
$SUB R ;type RECEIVED chars
$SUB V ;VIEW file
$SUB T ;goto TERMINAL mode
$SUB E ;goto ECHO mode
$SUB D ;Disconnect
$SUB Q ;Quiet
$SUB A ;Ascii
$SUB B ;Binary
"I" ,, (F%ITS!F%B) ;ITS binary
"N" ,, (F%ARPA) ;Network
"," ,, (F%COMMA)
0
OPTERR: hrroi 1,[asciz/Illegal Suboption
/]
psout
jrst SUBOPT
Subttl data
CHNTAB: 1,,INTER
block 35
LEVTAB: pclev1
exp 0,0
PCLEV1: 0
BUFFER: block bufsiz/4 + 2
HLPTXT: asciz/
MODEM commands for this version of the TOPS-20 modem program
have the following format:
@MODEM <option><suboptions> <file>
Where <option> is one of:
H Print (this) help text.
S Send a file
R Receive a file
T Terminal mode
E Echo mode
C make a call to auto-dialer or TTY line
C98596263 call up the SRI micom (no auto-dialers exist yet)
CTTY120 use TTY120 for the transfer
C:<host> do a transfer to <host> (not currently implemnted)
D disconnect and deassign autodialer or TTY line
and <sub-options> belong to the following list:
S View sent characters
R View receiverd characters
V View file (data only)
B use binary mode transfer
A use ascii mode transfer
I file is ITS style binary file
T go to terminal mode after transfer
N operate through ARPANet TIP or TAC
E go to echo mode after transfer
D disconnect after transfer
Q Transfer Quietly (no TTY messages)
Typing MODEM with no options will cause you to be droped into command
mode, where MODEM will wait for options, and return when the specified
action is complete (useful if you must transfer many files).
If a "call" is not placed using the C option, then the jobs controling
terminal is used for the file transfer.
/
PDLPTR: iowd 20,PDL
block 2
PDL: block 20
MODDEV: 0
OUTJFN: 0
FILJFN: 0
EOFFLG: 0
CMFLAG: 0
INTINS: 0
LSTREC: 0
OLDMOD: 0
OLDCOC: block 2
TIMTIM: 0
CMDBUF: block 20
DEVNAM: block 10
end start